use reqwest::{Client, Error};
use serde::{de::DeserializeOwned, Deserialize};
use serde_json::json as prasejson;
use std::collections::HashMap;

const TIMEOUT_MSEC: u64 = 5000;

pub async fn do_get<T>(url: &str, param_map: Option<HashMap<&str, &str>>) -> Result<T, Error>
where
    T: DeserializeOwned,
{
    let client = Client::builder()
        .timeout(std::time::Duration::from_millis(TIMEOUT_MSEC))
        .build()?;

    let mut request = client.get(url);

    if let Some(params) = param_map {
        request = request.query(&params);
    }

    let result = request.send().await;

    match result {
        Ok(response) => {
            let resp = response.json::<T>().await;
            resp
        }
        Err(e) => Err(e),
    }
}

pub async fn do_post(
    url: &str,
    param_map: Option<HashMap<String, String>>,
) -> Result<String, Error> {
    let client = Client::builder()
        .timeout(std::time::Duration::from_millis(TIMEOUT_MSEC))
        .build()?;

    let response = client
        .post(url)
        .form(&param_map.unwrap_or_default())
        .send()
        .await?
        .text()
        .await?;

    Ok(response)
}

/// 发送 POST JSON 请求
pub async fn do_post_json(
    url: &str,
    param_map: Option<HashMap<String, String>>,
) -> Result<String, Error> {
    let client = Client::builder()
        .timeout(std::time::Duration::from_millis(TIMEOUT_MSEC))
        .build()?;

    let json_body = if let Some(params) = param_map {
        prasejson!(params)
    } else {
        prasejson!({})
    };

    let response = client
        .post(url)
        .json(&json_body)
        .send()
        .await?
        .text()
        .await?;

    Ok(response)
}
